let override_ids = try!(source_ids_from_config(config, package.root()));
let (packages, resolve_with_overrides, sources) = {
- let rustc_host = config.rustc_host().to_string();
let mut registry = PackageRegistry::new(config);
if let Some(source) = source {
registry.preload(package.package_id().source_id(), source);
try!(registry.add_overrides(override_ids));
- let platform = target.as_ref().map(|e| &e[..]).or(Some(&rustc_host[..]));
+ let platform = target.as_ref().unwrap_or(&config.rustc_info().host);
- let method = Method::Required{
+ let method = Method::Required {
dev_deps: true, // TODO: remove this option?
features: &features,
uses_default_features: !no_default_features,
- target_platform: platform};
+ target_platform: Some(&platform[..]),
+ };
let resolved_with_overrides =
try!(ops::resolve_with_previous(&mut registry, package, method,
requested_target: target.clone(),
..Default::default()
};
- base.host = try!(scrape_target_config(config, config.rustc_host()));
+ base.host = try!(scrape_target_config(config, &config.rustc_info().host));
base.target = match target.as_ref() {
Some(triple) => try!(scrape_target_config(config, &triple)),
None => base.host.clone(),
} else {
try!(Context::filename_parts(None, config))
};
- let target_triple = target.unwrap_or(config.rustc_host()).to_string();
+ let target_triple = target.unwrap_or_else(|| {
+ &config.rustc_info().host[..]
+ }).to_string();
let engine = build_config.exec_engine.as_ref().cloned().unwrap_or({
Arc::new(Box::new(ProcessEngine))
});
/// otherwise it corresponds to the target platform.
fn dylib(&self, kind: Kind) -> CargoResult<(&str, &str)> {
let (triple, pair) = if kind == Kind::Host {
- (self.config.rustc_host(), &self.host_dylib)
+ (&self.config.rustc_info().host, &self.host_dylib)
} else {
- (&self.target_triple[..], &self.target_dylib)
+ (&self.target_triple, &self.target_dylib)
};
match *pair {
None => return Err(human(format!("dylib outputs are not supported \
.env("CARGO_MANIFEST_DIR", pkg.root())
.env("NUM_JOBS", &cx.jobs().to_string())
.env("TARGET", &match kind {
- Kind::Host => cx.config.rustc_host(),
+ Kind::Host => &cx.config.rustc_info().host[..],
Kind::Target => cx.target_triple(),
})
.env("DEBUG", &profile.debuginfo.to_string())
.env("OPT_LEVEL", &profile.opt_level.to_string())
.env("PROFILE", if cx.build_config.release {"release"} else {"debug"})
- .env("HOST", &cx.config.rustc_host());
+ .env("HOST", &cx.config.rustc_info().host);
// Be sure to pass along all enabled features for this package, this is the
// last piece of statically known information that we have.
v.sort();
v
});
- let extra = util::short_hash(&(cx.config.rustc_version(), target, &features,
- profile));
+ let extra = util::short_hash(&(&cx.config.rustc_info().verbose_version,
+ target, &features, profile));
debug!("extra {:?} {:?} {:?} = {}", target, profile, features, extra);
// Next, recursively calculate the fingerprint for all of our dependencies.
use std::ffi::OsString;
use std::fs;
use std::io::prelude::*;
-use std::path::{self, Path, PathBuf};
+use std::path::{self, PathBuf};
use std::sync::Arc;
use core::{SourceMap, Package, PackageId, PackageSet, Target, Resolve};
pub overrides: HashMap<String, BuildOutput>,
}
-/// Run `rustc` to figure out what its current version string is.
-///
-/// The second element of the tuple returned is the target triple that rustc
-/// is a host for.
-pub fn rustc_version<P: AsRef<Path>>(rustc: P) -> CargoResult<(String, String)> {
- let output = try!(try!(util::process(rustc.as_ref()))
- .arg("-vV")
- .exec_with_output());
- let output = try!(String::from_utf8(output.stdout).map_err(|_| {
- internal("rustc -v didn't return utf8 output")
- }));
- let triple = {
- let triple = output.lines().filter(|l| {
- l.starts_with("host: ")
- }).map(|l| &l[6..]).next();
- let triple = try!(triple.chain_error(|| {
- internal("rustc -v didn't have a line for `host:`")
- }));
- triple.to_string()
- };
- Ok((output, triple))
-}
-
// Returns a mapping of the root package plus its immediate dependencies to
// where the compiled libraries are all located.
pub fn compile_targets<'a, 'cfg: 'a>(targets: &[(&'a Target, &'a Profile)],
return rustcs.into_iter().map(|(mut rustc, kind)| {
let name = package.name().to_string();
let is_path_source = package.package_id().source_id().is_path();
- let show_warnings = package.package_id() == cx.resolve.root() ||
- is_path_source;
- if !show_warnings {
- rustc.arg("-Awarnings");
+ let allow_warnings = package.package_id() == cx.resolve.root() ||
+ is_path_source;
+ if !allow_warnings {
+ if cx.config.rustc_info().cap_lints {
+ rustc.arg("--cap-lints").arg("allow");
+ } else {
+ rustc.arg("-Awarnings");
+ }
}
let has_custom_args = profile.rustc_args.is_some();
let exec_engine = cx.exec_engine.clone();
pub use self::cargo_compile::{compile, compile_pkg, CompileOptions};
pub use self::cargo_compile::{CompileFilter, CompileMode};
pub use self::cargo_read_manifest::{read_manifest,read_package,read_packages};
-pub use self::cargo_rustc::{compile_targets, Compilation, Layout, Kind, rustc_version};
+pub use self::cargo_rustc::{compile_targets, Compilation, Layout, Kind};
pub use self::cargo_rustc::{Context, LayoutProxy};
pub use self::cargo_rustc::Platform;
pub use self::cargo_rustc::{BuildOutput, BuildConfig, TargetConfig};
use rustc_serialize::{Encodable,Encoder};
use toml;
use core::{MultiShell, Package};
-use ops;
-use util::{CargoResult, ChainError, internal, human};
+use util::{CargoResult, ChainError, Rustc, internal, human};
use util::toml as cargo_toml;
pub struct Config {
home_path: PathBuf,
shell: RefCell<MultiShell>,
- rustc_version: String,
- /// The current host and default target of rustc
- rustc_host: String,
+ rustc_info: Rustc,
values: RefCell<HashMap<String, ConfigValue>>,
values_loaded: Cell<bool>,
cwd: PathBuf,
This probably means that $HOME was not set.")
})),
shell: RefCell::new(shell),
- rustc_version: String::new(),
- rustc_host: String::new(),
+ rustc_info: Rustc::blank(),
cwd: cwd,
values: RefCell::new(HashMap::new()),
values_loaded: Cell::new(false),
pub fn rustdoc(&self) -> &Path { &self.rustdoc }
- /// Return the output of `rustc -v verbose`
- pub fn rustc_version(&self) -> &str { &self.rustc_version }
-
- /// Return the host platform and default target of rustc
- pub fn rustc_host(&self) -> &str { &self.rustc_host }
+ pub fn rustc_info(&self) -> &Rustc { &self.rustc_info }
pub fn values(&self) -> CargoResult<Ref<HashMap<String, ConfigValue>>> {
if !self.values_loaded.get() {
}
fn scrape_rustc_version(&mut self) -> CargoResult<()> {
- let (rustc_version, rustc_host) = try!(ops::rustc_version(&self.rustc));
- self.rustc_version = rustc_version;
- self.rustc_host = rustc_host;
+ self.rustc_info = try!(Rustc::new(&self.rustc));
Ok(())
}
pub use self::config::Config;
-pub use self::process_builder::{process, ProcessBuilder};
+pub use self::dependency_queue::Dependency;
+pub use self::dependency_queue::{DependencyQueue, Fresh, Dirty, Freshness};
pub use self::errors::{CargoResult, CargoError, ChainError, CliResult};
pub use self::errors::{CliError, ProcessError};
-pub use self::errors::{process_error, internal_error, internal, human};
pub use self::errors::{Human, caused_human};
+pub use self::errors::{process_error, internal_error, internal, human};
+pub use self::graph::Graph;
+pub use self::hex::{to_hex, short_hash};
+pub use self::lev_distance::{lev_distance};
pub use self::paths::{join_paths, path2bytes, bytes2path, dylib_path};
pub use self::paths::{normalize_path, dylib_path_envvar, without_prefix};
-pub use self::lev_distance::{lev_distance};
-pub use self::hex::{to_hex, short_hash};
-pub use self::dependency_queue::{DependencyQueue, Fresh, Dirty, Freshness};
-pub use self::dependency_queue::Dependency;
-pub use self::graph::Graph;
-pub use self::to_url::ToUrl;
+pub use self::process_builder::{process, ProcessBuilder};
+pub use self::rustc::Rustc;
+pub use self::sha256::Sha256;
pub use self::to_semver::ToSemver;
+pub use self::to_url::ToUrl;
pub use self::vcs::{GitRepo, HgRepo};
-pub use self::sha256::Sha256;
pub mod config;
pub mod errors;
mod sha256;
mod shell_escape;
mod vcs;
+mod rustc;
--- /dev/null
+use std::path::Path;
+
+use util::{self, CargoResult, internal, ChainError};
+
+pub struct Rustc {
+ pub verbose_version: String,
+ pub host: String,
+ pub cap_lints: bool,
+}
+
+impl Rustc {
+ /// Run the compiler at `path` to learn varioues pieces of information about
+ /// it.
+ ///
+ /// If successful this function returns a description of the compiler along
+ /// with a list of its capabilities.
+ pub fn new<P: AsRef<Path>>(path: P) -> CargoResult<Rustc> {
+ let mut cmd = try!(util::process(path.as_ref()));
+ cmd.arg("-vV");
+
+ let mut ret = Rustc::blank();
+ let mut first = cmd.clone();
+ first.arg("--cap-lints").arg("allow");
+ let output = match first.exec_with_output() {
+ Ok(output) => { ret.cap_lints = true; output }
+ Err(..) => try!(cmd.exec_with_output()),
+ };
+ ret.verbose_version = try!(String::from_utf8(output.stdout).map_err(|_| {
+ internal("rustc -v didn't return utf8 output")
+ }));
+ ret.host = {
+ let triple = ret.verbose_version.lines().filter(|l| {
+ l.starts_with("host: ")
+ }).map(|l| &l[6..]).next();
+ let triple = try!(triple.chain_error(|| {
+ internal("rustc -v didn't have a line for `host:`")
+ }));
+ triple.to_string()
+ };
+ Ok(ret)
+ }
+
+ pub fn blank() -> Rustc {
+ Rustc {
+ verbose_version: String::new(),
+ host: String::new(),
+ cap_lints: false,
+ }
+ }
+}
assert_that(p.cargo_process("test").arg("-v"),
execs().with_status(0));
});
+
+test!(lints_are_suppressed {
+ let a = git::new("a", |p| {
+ p.file("Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "
+ use std::option;
+ ")
+ }).unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = {{ git = '{}' }}
+ "#, a.url()))
+ .file("src/lib.rs", "");
+
+ assert_that(p.cargo_process("build"),
+ execs().with_status(0).with_stdout(&format!("\
+{updating} git repository `[..]`
+{compiling} a v0.5.0 ([..])
+{compiling} foo v0.0.1 ([..])
+", compiling = COMPILING, updating = UPDATING)));
+});
+
+test!(denied_lints_are_allowed {
+ let enabled = super::RUSTC.with(|r| r.cap_lints);
+ if !enabled { return }
+
+ let a = git::new("a", |p| {
+ p.file("Cargo.toml", r#"
+ [project]
+ name = "a"
+ version = "0.5.0"
+ authors = []
+ "#)
+ .file("src/lib.rs", "
+ #![deny(warnings)]
+ use std::option;
+ ")
+ }).unwrap();
+
+ let p = project("foo")
+ .file("Cargo.toml", &format!(r#"
+ [package]
+ name = "foo"
+ version = "0.0.1"
+ authors = []
+
+ [dependencies]
+ a = {{ git = '{}' }}
+ "#, a.url()))
+ .file("src/lib.rs", "");
+
+ assert_that(p.cargo_process("build"),
+ execs().with_status(0).with_stdout(&format!("\
+{updating} git repository `[..]`
+{compiling} a v0.5.0 ([..])
+{compiling} foo v0.0.1 ([..])
+", compiling = COMPILING, updating = UPDATING)));
+});
#[macro_use]
extern crate log;
+use cargo::util::Rustc;
+
mod support;
macro_rules! test {
($name:ident $expr:expr) => (
mod test_cargo_version;
mod test_shell;
+thread_local!(static RUSTC: Rustc = Rustc::new("rustc").unwrap());
+
fn rustc_host() -> String {
- cargo::ops::rustc_version("rustc").unwrap().1
+ RUSTC.with(|r| r.host.clone())
}
fn is_nightly() -> bool {
- let version_info = cargo::ops::rustc_version("rustc").unwrap().0;
- version_info.contains("-nightly") || version_info.contains("-dev")
+ RUSTC.with(|r| {
+ r.verbose_version.contains("-nightly") ||
+ r.verbose_version.contains("-dev")
+ })
}
fn can_panic() -> bool {
- let host = cargo::ops::rustc_version("rustc").unwrap().1;
- !host.contains("msvc")
+ RUSTC.with(|r| !r.host.contains("msvc"))
}